package com.abocode.aichat.app.exception;

import com.abocode.aichat.app.utils.StringUtil;

import java.util.*;

/**
 * Created by guanxf on 2015/12/16.
 */
public class ContextRuntimeException extends RuntimeException {
    private final Map<String, Object> result;

    public ContextRuntimeException(String status, String message) {
        this(status, message, null);
    }

    public ContextRuntimeException(String status, String message, Throwable throwable) {
        super(message, throwable);
        this.result = new HashMap<>();
        this.result.put("status", status);
        this.result.put("time", StringUtil.getDateTime(new Date()));
        this.result.put("message", message);
    }

    public ContextRuntimeException addContextValue(String label, Object value) {
        result.put(label, value);
        return this;
    }

    public Set<String> getContextLabels() {
        return result.keySet();
    }

    public Map<String, Object> getContextEntries() {
        return Collections.unmodifiableMap(result);
    }

    @Override
    public String getMessage() {
        return getFormattedExceptionMessage(super.getMessage());
    }

    public String getRawMessage() {
        return super.getMessage();
    }

    private String getFormattedExceptionMessage(final String baseMessage) {
        final StringBuilder buffer = new StringBuilder(256);
        if (baseMessage != null) {
            buffer.append(baseMessage);
        }

        if (result.size() > 0) {
            if (buffer.length() > 0) {
                buffer.append('\n');
            }
            buffer.append("Exception Context:\n");

            int i = 0;
            for (final Map.Entry<String, Object> pair : result.entrySet()) {
                buffer.append("\t[");
                buffer.append(++i);
                buffer.append(':');
                buffer.append(pair.getKey());
                buffer.append("=");
                final Object value = pair.getValue();
                if (value == null) {
                    buffer.append("null");
                } else {
                    String valueStr;
                    try {
                        valueStr = value.toString();
                    } catch (final Exception e) {
                        valueStr = "Exception thrown on toString(): " + e.getMessage();
                    }
                    buffer.append(valueStr);
                }
                buffer.append("]\n");
            }
            buffer.append("---------------------------------");
        }
        return buffer.toString();
    }
}
